using System.Collections.Generic;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;

namespace GemTowerDefence
{
  public class TileMap
  {
    private readonly Dictionary<TileType, Texture2D> _tileTextures;

    public List<MapRow> Rows { get; set; }

    public int Width { get; private set; }
    public int Height { get; private set; }

    public Queue<Vector2> Waypoints { get; private set; }

    public List<Vector2> HaveToGoPonts { get; private set; }

    public TileMap()
    {
      _tileTextures = new Dictionary<TileType, Texture2D>();
      Waypoints = new Queue<Vector2>();
      HaveToGoPonts = new List<Vector2>();

      Width = 40;
      Height = 36;
      Rows = new List<MapRow>();

      // fill with grass by default
      for (var y = 0; y < Height; y++)
      {
        var thisRow = new MapRow();
        for (var x = 0; x < Width; x++)
          thisRow.Columns.Add(new MapCell(TileType.Grass));
        Rows.Add(thisRow);
      }

      Waypoints.Enqueue(new Vector2(0, 2.8F) * Game.TextureSize); // start waypoint
      HaveToGoPonts.Add(new Vector2(0, 3));

      // sand will be our road
      for (int x = 0; x < 9; x++)
        Rows[3].Columns[x].Type = TileType.Road;
      Rows[3].Columns[9].Type = TileType.Plate;
      Rows[3].Columns[10].Type = TileType.Plate; // 1 waypoint
      Waypoints.Enqueue(new Vector2(9.8F, 2.8F) * Game.TextureSize);
      HaveToGoPonts.Add(new Vector2(10, 3));
      Rows[2].Columns[10].Type = TileType.Plate;
      Rows[4].Columns[10].Type = TileType.Plate;

      for (int y = 5; y < 14; y++)
        Rows[y].Columns[10].Type = TileType.Road;
      Rows[14].Columns[10].Type = TileType.Plate;
      Rows[15].Columns[10].Type = TileType.Plate; // 2 waypoint
      Waypoints.Enqueue(new Vector2(9.8F, 14.8F) * Game.TextureSize);
      HaveToGoPonts.Add(new Vector2(10, 15));
      Rows[15].Columns[11].Type = TileType.Plate;
      Rows[16].Columns[10].Type = TileType.Plate;

      for (int x = 12; x < 33; x++)
        Rows[15].Columns[x].Type = TileType.Road;
      Rows[15].Columns[32].Type = TileType.Plate;
      Rows[15].Columns[33].Type = TileType.Plate; // 3 waypoint
      Waypoints.Enqueue(new Vector2(32.8F, 14.8F) * Game.TextureSize);
      HaveToGoPonts.Add(new Vector2(33, 15));
      Rows[15].Columns[34].Type = TileType.Plate;
      Rows[14].Columns[33].Type = TileType.Plate;

      for (int y = 5; y < 14; y++)
        Rows[y].Columns[33].Type = TileType.Road;
      Rows[4].Columns[33].Type = TileType.Plate;
      Rows[3].Columns[32].Type = TileType.Plate;
      Rows[3].Columns[33].Type = TileType.Plate; // 4 waypoint
      Waypoints.Enqueue(new Vector2(32.8F, 2.8F) * Game.TextureSize);
      HaveToGoPonts.Add(new Vector2(33, 3));
      Rows[2].Columns[33].Type = TileType.Plate;

      for (int x = 23; x < 32; x++)
        Rows[3].Columns[x].Type = TileType.Road;
      Rows[4].Columns[21].Type = TileType.Plate;
      Rows[3].Columns[20].Type = TileType.Plate;
      Rows[3].Columns[21].Type = TileType.Plate; // 5 waypoint
      Waypoints.Enqueue(new Vector2(20.8F, 2.7F) * Game.TextureSize);
      HaveToGoPonts.Add(new Vector2(21, 3));
      Rows[3].Columns[22].Type = TileType.Plate;

      for (int y = 5; y < 26; y++)
        Rows[y].Columns[21].Type = TileType.Road;
      Rows[26].Columns[21].Type = TileType.Plate;
      Rows[27].Columns[21].Type = TileType.Plate; // 6 waypoint
      Waypoints.Enqueue(new Vector2(20.8F, 26.8F) * Game.TextureSize);
      HaveToGoPonts.Add(new Vector2(21, 27));
      Rows[28].Columns[21].Type = TileType.Plate; 
      Rows[27].Columns[22].Type = TileType.Plate;

      for (int x = 23; x < 32; x++)
        Rows[27].Columns[x].Type = TileType.Road;
      Rows[27].Columns[32].Type = TileType.Plate;
      Rows[26].Columns[33].Type = TileType.Plate;
      Rows[27].Columns[33].Type = TileType.Plate; // 7 waypoint
      Waypoints.Enqueue(new Vector2(32.8F, 26.8F) * Game.TextureSize);
      HaveToGoPonts.Add(new Vector2(33, 27));
      Rows[28].Columns[33].Type = TileType.Plate;

      for (int y = 29; y < 36; y++)
        Rows[y].Columns[33].Type = TileType.Road;

      Waypoints.Enqueue(new Vector2(32.8F, 35) * Game.TextureSize); // last waypoint
      HaveToGoPonts.Add(new Vector2(33, 35));
    }

    public void AddTexture(TileType type, Texture2D texture)
    {
      _tileTextures.Add(type, texture);
    }

    public void Draw(SpriteBatch batch)
    {
      for (var x = 0; x < Width; x++)
      {
        for (var y = 0; y < Height; y++)
        {
          var tileType = Rows[y].Columns[x].Type;
          if (tileType == TileType.None) continue;
          var texture = _tileTextures[tileType];
          const int size = Game.TextureSize;
          batch.Draw(texture, new Rectangle(x * size, y * size, size, size), Color.White);
        }
      }
    }

    public TileType GetCellType(int cellX, int cellY)
    {
      if (cellX < 0 || cellX > Width - Game.PanelSize || cellY < 0 || cellY > Height)
        return 0;

      return Rows[cellY].Columns[cellX].Type;
    }

  }

  public class MapRow
  {
    public List<MapCell> Columns { get; set; }

    public MapRow()
    {
      Columns = new List<MapCell>();
    }
  }

  public enum TileType
  {
    None,
    Water,
    Road,
    Grass,
    Plate,
  }
}